package com.newflypig.jblog.model;

import java.sql.Timestamp;
import java.util.Date;
import java.util.HashSet;
import java.util.LinkedHashSet;
import java.util.Set;

import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.ManyToOne;
import javax.persistence.OrderBy;
import javax.persistence.Table;
import javax.persistence.Transient;

import com.newflypig.jblog.util.BlogUtils;

@Entity
@Table(name = "jblog_article", catalog = "jblog2")
public class Article implements java.io.Serializable {

	private static final long serialVersionUID = 9169337066300818107L;
	
	public static final short TYPE_ARTICLE = 0;	//正式文章
	public static final short TYPE_ARCHIVE_HEAD = 1;	//头部不带标题文字块
	public static final short TYPE_ARCHIVE_FOOT = 2;	//底部不带标题文字块
	public static final short TYPE_DATA    = 3;			//外部数据引用，其html部分由url通过HTTPGET获取
	public static final short TYPE_WIDGET  = 11;		//自定义插件
	public static final short TYPE_WIDGET_TAGS = 12; 	//标签插件
	public static final short TYPE_WIDGET_ARCHIVE = 13;	//存档插件
	
	public static final short STATE_EDIT    = 0;	//编辑状态，暂时不显示
	public static final short STATE_PUBLISH = 1;	//发布状态，正常显示
	public static final short STATE_DELETE  = 2;	//删除状态，前台后台都不显示，垃圾箱中
	
	private Integer   articleId;
	private String    title;
	private String    html;
	private String    markdown;
	private Short	  type = 0;
	private String    url;
	private String    urlName;
	private Short     state = 1;
	private Long      rate = 0L;
	private Integer   index = 0;
	private Timestamp createDate = new Timestamp(new Date().getTime());
	private Timestamp lastEditDate = new Timestamp(new Date().getTime());
	private Boolean   showInList = false;	//是否在「日志列表」中显示
	
	private Archive	  archive;
	
	private Set<Menu> menus = new HashSet<Menu>(0);
	private Set<Tag>  tags  = new LinkedHashSet<Tag>(0);
	
	private String tagsStr = "";
	private String menusStr= "";

	public Article() {
	}
	
	public Article(Integer articleId) {
		this.articleId=articleId;
	}
	
	public Article(Integer articleId, String title, Short type, String url, String urlName, Short state, Long rate, Timestamp createDate, Timestamp lastEditDate) {
		this.articleId = articleId;
		this.title = title;
		this.type = type;
		this.url = url;
		this.urlName = urlName;
		this.state = state;
		this.rate = rate;
		this.createDate = createDate;
		this.lastEditDate = lastEditDate;
	}
	
	public Article(String html){
		this.html = html;
	}
	
	public Article(Integer articleId, String title, String urlName, Timestamp createDate, String html){
		this.articleId = articleId;
		this.title = title;
		this.urlName = urlName;
		this.createDate = createDate;
		this.html = html;
	}
	
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	@Column(name = "id")
	public Integer getArticleId() {
		return this.articleId;
	}

	public void setArticleId(Integer articleId) {
		this.articleId = articleId;
	}

	@Column(name = "create_dt", length = 19)
	public Timestamp getCreateDate() {
		return this.createDate;
	}

	public void setCreateDate(Timestamp createDate) {
		this.createDate = createDate;
	}
	
	@Column(name = "last_edit_dt", length = 19)
	public Timestamp getLastEditDate() {
		return this.lastEditDate;
	}

	public void setLastEditDate(Timestamp lastEditDate) {
		this.lastEditDate = lastEditDate;
	}

	@Column(name = "html")
	public String getHtml() {
		return this.html;
	}

	public void setHtml(String html) {
		this.html = html;
	}

	@Column(name = "markdown")
	public String getMarkdown() {
		return markdown;
	}

	public void setMarkdown(String markdown) {
		this.markdown = markdown;
	}

	@Column(name = "title", length = 45)
	public String getTitle() {
		return this.title;
	}

	public void setTitle(String title) {
		this.title = BlogUtils.html(title);
	}
	
	@Column(name = "type" , nullable = false)
	public Short getType() {
		return type;
	}

	public void setType(Short type) {
		this.type = type;
	}

	@Column(name = "url")
	public String getUrl() {
		return url;
	}

	public void setUrl(String url) {
		this.url = url;
	}

	@Column(name = "url_name")
	public String getUrlName() {
		return urlName;
	}

	public void setUrlName(String urlName) {
		this.urlName = urlName;
	}
	
	@Column(name = "state", nullable = false)
	public Short getState() {
		return state;
	}

	public void setState(Short state) {
		this.state = state;
	}

	@Column(name = "rate" , nullable = false)
	public Long getRate() {
		return this.rate;
	}

	public void setRate(Long rate) {
		this.rate = rate;
	}
	
	@Column(name = "page_index")
	public Integer getIndex() {
		return index;
	}

	public void setIndex(Integer index) {
		this.index = index;
	}
	
	@ManyToOne(cascade = CascadeType.ALL , fetch = FetchType.LAZY)           
    @JoinColumn(name = "archive_id")
	public Archive getArchive() {
		return archive;
	}

	public void setArchive(Archive archive) {
		this.archive = archive;
	}

	@ManyToMany(fetch = FetchType.LAZY, cascade = CascadeType.ALL)
	@JoinTable(name="jblog_menu_article",
		joinColumns={@JoinColumn(name="jblog_article_id")},
		inverseJoinColumns={@JoinColumn(name="jblog_menu_id")}
	)
	public Set<Menu> getMenus() {
		return this.menus;
	}

	public void setMenus(Set<Menu> menus) {
		this.menus = menus;
	}
	
	
	@ManyToMany(fetch=FetchType.LAZY,mappedBy="articles")
	@OrderBy("id ASC")
	public Set<Tag> getTags() {
		return this.tags;
	}

	public void setTags(Set<Tag> tags) {
		this.tags = tags;
	}
	
	@Column(name = "show_in_list")
	public Boolean getShowInList() {
		return showInList;
	}

	public void setShowInList(Boolean showInList) {
		this.showInList = showInList;
	}

	@Transient
	public String getTagsStr() {
		return this.tagsStr;
	}

	public void setTagsStr(String tagsStr) {
		this.tagsStr = tagsStr;
	}
	
	public String buildTagsStr(){
		String str = this.tags.stream().reduce(
			new String(),
			(result,item) -> result += (item.getTitle() + ","),
			(u,t) -> u
		);
		this.tagsStr = str;
		return str;
	}
	
	@Transient
	public String getMenusStr() {
		return this.menusStr;
	}

	public void setMenusStr(String menusStr) {
		this.menusStr = menusStr;
	}
	
	public String buildMenusStr(){
		this.menusStr = this.menus.stream().reduce(
			new String(),
			(result,item) -> result += (item.getTitle() + ","),
			(u,t) -> u
		);
		return this.menusStr;
	}
}